/*
 * handle_server.cpp
 *
 *  Created on: Nov 27, 2013
 *      Author: killerg
 */

#include "robot_deps.h"

#include "share/msg.h"
#include "share/cs_msg.pb.h"
#include "share/json/json.h"
#include "share/util.h"
#include "share/msg_handler.h"
#include "share/patterns.h"
#include "share/clock.h"
#include "share/sl_msg.pb.h"

#include "bot.h"
#include "bots.h"

//#define LOG_ROBOT
#ifdef LOG_ROBOT
    #define RANGE_LOG(a...) tracer_t<1> t(a)
    #define LOC_LOG(a...) tracer_t<1>::log(a)
#else
    #define RANGE_LOG(a...)
    #define LOC_LOG(a...)
#endif

using namespace std;



void handle_secho(bot_t* robot, cs::SMsg* msg) {
    RANGE_LOG("handle_sauth");

    auto echo = msg->echo();

    double latency = g_bots.clock->eclipse - echo.echo().stamp();
    robot->stat.latency_all += latency;
    ++robot->stat.num;
    robot->stat.latency_max = max(robot->stat.latency_max, latency);
    robot->stat.latency_min = min(robot->stat.latency_min, latency);
}

void handle_sload(bot_t* robot, cs::SMsg* msg) {
    RANGE_LOG("handle_sload");

    auto load = msg->load();
    if (load.has_player()) {
        robot->stage = EServerPlaying;
        CREATE_CS_CMSG(CArenaRefresh, arenarefresh);
        robot->net.send(___msg);

    } else if (load.has_already_online()) {
        robot->stage = EErrorServer;
    } else if (load.has_timeout()) {
        robot->stage = EErrorServer;
    } else {
        CREATE_CS_CMSG(CCreate, create);
        create->set_name(fmt_str("p%lld", robot->data.playerid % co::MaxAccountNum));
        create->set_sex(random(0,1) ? cs::EPS_Male : cs::EPS_Femal);
        robot->net.send(___msg);
        robot->stage = EServerCreating;
    }

    LOC_LOG("has player:%d\n", load.has_player());
}
void handle_screate(bot_t* robot, cs::SMsg* msg) {
    RANGE_LOG("handle_screate");

    auto create = msg->create();
    if (create.ok()) {
        CREATE_CS_CMSG(CLoad, load);
        robot->net.send(___msg);
        robot->stage = EServerLoading;
    } else {
        robot->stage = EErrorServer;
    }
    LOC_LOG("create:%d\n", create.ok());
}

void handle_sarenarefresh(bot_t* robot, cs::SMsg* msg) {

}

template<>
struct msg_traits<cs::SMsg> {
    typedef typename cs::SMsg MsgT;
    typedef bot_t SessionT;

    typedef void (*HandlerT)(SessionT*, MsgT*);

    enum {
        MsgID_ARRAYSIZE = cs::SMsgID_ARRAYSIZE,
    };

    static bool is_valid_msgid(int id) {
        return cs::SMsgID_IsValid(id);
    }

    static void init_handlers(HandlerT handlers[]) {
        for (int i = 0; i < MsgID_ARRAYSIZE; ++i)
            handlers[i] = NULL;

        handlers[cs::ID_SEcho] = handle_secho;
        handlers[cs::ID_SLoad] = handle_sload;
        handlers[cs::ID_SCreate] = handle_screate;
        handlers[cs::ID_SArenaRefresh] = handle_sarenarefresh;
    }
};

void bot_t::update_smsg() {
    if (net.is_connected()) {
        auto msg = net.recv<cs::SMsg>();
        while (msg) {
            Singleton<msg_handler_t<cs::SMsg>>::Instance().handle(this, msg);
            delete msg;
            msg = net.recv<cs::SMsg>();
        }
    }
}
